// Copyright 2018 The OpenPitrix Authors. All rights reserved.
// Use of this source code is governed by a Apache license
// that can be found in the LICENSE file.

//go:generate go run gen_helper.go
//go:generate go fmt ./...

// +build ignore

package main

import (
	"fmt"
	"html/template"
	"log"
	"os"
	"strings"

	"openpitrix.io/openpitrix/pkg/util/stringutil"
)

var syncTemplate = template.Must(template.New("").Funcs(template.FuncMap{
	"snakeCase":  stringutil.CamelCaseToUnderscore,
	"pascalCase": stringutil.UnderscoreToCamelCase,
	"escape": func(s string) string {
		return strings.Replace(s, "_", "", -1)
	},
	"columnId": func(table string) string {
		if table == "app_version" {
			return "version"
		}
		if table == "cluster_node" {
			return "node"
		}
		return table
	},
}).Parse(`
func Check{{pascalCase .}}sPermission(ctx context.Context, resourceIds []string) ([]*models.{{pascalCase .}}, error) {
	if len(resourceIds) == 0 {
		return nil, nil
	}
	var sender = senderutil.GetSenderFromContext(ctx)
	var {{escape .}}s []*models.{{pascalCase .}}
	_, err := pi.Global().DB(ctx).
		Select(models.{{pascalCase .}}Columns...).
		From(constants.Table{{pascalCase .}}).
		Where(db.Eq(constants.Column{{columnId . | pascalCase}}Id, resourceIds)).Load(&{{escape .}}s)
	if err != nil {
		return nil, gerr.NewWithDetail(ctx, gerr.Internal, err, gerr.ErrorInternalError)
	}
	if sender != nil && !sender.IsGlobalAdmin() {
		for _, {{escape .}} := range {{escape .}}s {
			if {{escape .}}.Owner != sender.UserId {
				return nil, gerr.New(ctx, gerr.PermissionDenied, gerr.ErrorResourceAccessDenied, {{escape .}}.{{columnId . | pascalCase}}Id)
			}
		}
	}
	if len({{escape .}}s) == 0 {
		return nil, gerr.New(ctx, gerr.NotFound, gerr.ErrorResourceNotFound, resourceIds)
	}
	return {{escape .}}s, nil
}

func Check{{pascalCase .}}Permission(ctx context.Context, resourceId string) (*models.{{pascalCase .}}, error) {
	if len(resourceId) == 0 {
		return nil, nil
	}
	var sender = senderutil.GetSenderFromContext(ctx)
	var {{escape .}}s []*models.{{pascalCase .}}
	_, err := pi.Global().DB(ctx).
		Select(models.{{pascalCase .}}Columns...).
		From(constants.Table{{pascalCase .}}).
		Where(db.Eq(constants.Column{{columnId . | pascalCase}}Id, resourceId)).Load(&{{escape .}}s)
	if err != nil {
		return nil, gerr.NewWithDetail(ctx, gerr.Internal, err, gerr.ErrorInternalError)
	}
	if sender != nil && !sender.IsGlobalAdmin() {
		for _, {{escape .}} := range {{escape .}}s {
			if {{escape .}}.Owner != sender.UserId {
				return nil, gerr.New(ctx, gerr.PermissionDenied, gerr.ErrorResourceAccessDenied, {{escape .}}.{{columnId . | pascalCase}}Id)
			}
		}
	}
	if len({{escape .}}s) == 0 {
		return nil, gerr.New(ctx, gerr.NotFound, gerr.ErrorResourceNotFound, resourceId)
	}
	return {{escape .}}s[0], nil
}
`))

type Model struct {
	Name string
	Key  string
}

func main() {
	var models = []string{
		"repo", "app", "app_version", "cluster", "cluster_node",
		"job", "task", "repo_event", "runtime", "key_pair",
	}

	permissions := make(map[string]*os.File)

	for _, m := range models {
		var packageName string

		switch m {
		case "app_version":
			packageName = "app"
		case "cluster_node":
			packageName = "cluster"
		case "key_pair":
			packageName = "cluster"
		case "repo_event":
			packageName = "repo_indexer"
		default:
			packageName = m
		}

		fileName := fmt.Sprintf("%s/permission.go", packageName)

		_, isExist := permissions[fileName]
		if !isExist {
			f, err := os.Create(fileName)
			if err != nil {
				log.Fatal(err)
			}
			defer f.Close()

			f.Write([]byte(fmt.Sprintf(`// Copyright 2018 The OpenPitrix Authors. All rights reserved.
// Use of this source code is governed by a Apache license
// that can be found in the LICENSE file.

// Auto generated by 'go run gen_helper.go', DO NOT EDIT.

package %s

import (
	"context"

	"openpitrix.io/openpitrix/pkg/constants"
	"openpitrix.io/openpitrix/pkg/db"
	"openpitrix.io/openpitrix/pkg/gerr"
	"openpitrix.io/openpitrix/pkg/models"
	"openpitrix.io/openpitrix/pkg/pi"
	"openpitrix.io/openpitrix/pkg/util/senderutil"
)
`, packageName)))
			permissions[fileName] = f
		}

		syncTemplate.Execute(permissions[fileName], m)
	}
}
